package controller;

import entity.User;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;
import javafx.util.Duration;
import service.UserService;
import service.impl.UserServiceImpl;

import java.io.IOException;
import java.net.URL;
import java.util.Objects;
import java.util.ResourceBundle;

/**
 * 聊天室控制类
 *
 * @author Mr.Alpaca
 * @version 1.0.0
 */
public class ForumController implements Initializable {
    public ListView<Label> userListView;
    public Label idLabel;
    public Label portLabel;
    public TextArea forumTextArea;
    public TextArea inputTextArea;
    public Button sendBtn;
    public Button emptyBtn;
    /**
     * 服务类
     */
    private final UserService service = UserServiceImpl.getService();
    /**
     * 当前界面的操作用户对象
     */
    private User user;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // 设置时间线定期刷新组件
        setupTimeLine();
        // 关闭聊天室则该用户下线
        offline();
        // 设置用户输入框事件
        setupInputTextArea();
    }

    /**
     * 用于从其他控制器传入参数到本控制器
     * 并展示用户信息
     *
     * @param user 用户
     */
    public void passUser(User user) {
        this.user = user;
        showUserMessage();
    }

    /**
     * 获取当前在线用户并展示账号,使用端口等信息
     */
    private void showUserMessage() {
        idLabel.setText(String.valueOf(user.getId()));
        portLabel.setText(String.valueOf(user.getSocket().getLocalPort()));
    }

    /**
     * 设置时间线事件,每隔一段时间更新组件
     * 1.ListView定期刷新当前所有在线用户
     * 并为每个Item绑定事件
     * 2.更新聊天室留言板信息
     */
    private void setupTimeLine() {
        // 在线用户列表动画帧,用于实时更新在线用户列表
        KeyFrame userListViewFrame = new KeyFrame(Duration.seconds(1), event -> {
            ObservableList<Label> itemList = FXCollections.observableArrayList();
            service.getOnlineUserList().forEach(user -> {
                Label label = new Label(user.getName() + " " + (user.isOnlineFlag() ? "(在线)" : "(离线)"));
                label.setOnMouseClicked(clickEvent -> {
                    // 双击item进入私聊界面
                    if (clickEvent.getClickCount() > 1) {
                        openPrivateChat(user);
                    }
                });
                itemList.add(label);
            });
            userListView.setItems(itemList);
        });
        // 论坛留言板动画帧,实时更新留言
        KeyFrame forumTextAreaFrame = new KeyFrame(Duration.millis(500), event -> {
            // 获取留言板更新前滑动位置,以便更新文本后回复原位
            double v = forumTextArea.getScrollTop();
            forumTextArea.setText(service.getMessageBoard());
            forumTextArea.setScrollTop(v);
        });
        // 开启动画
        Timeline timeline = new Timeline();
        timeline.getKeyFrames().addAll(userListViewFrame, forumTextAreaFrame);
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.setAutoReverse(true);
        timeline.play();
    }

    /**
     * 绑定退出事件
     */
    private void offline() {
        idLabel.sceneProperty().addListener((observableScene, oldScene, newScene) -> {
            if (oldScene == null && newScene != null) {
                newScene.windowProperty().addListener((observableWindow, oldWindow, newWindow) -> {
                    if (oldWindow == null && newWindow != null) {
                        newWindow.setOnCloseRequest(event -> {
                            // 用户下线
                            service.offlineUser(user.getId());
                        });
                    }
                });
            }
        });
    }

    /**
     * 设置文本框属性:
     * 输入框:
     * 1.自动换行
     * 2.获得焦点
     */
    private void setupInputTextArea() {
        inputTextArea.setWrapText(true);
        inputTextArea.requestFocus();
    }

    /**
     * 论坛群聊发送信息事件
     *
     * @param actionEvent 事件
     */
    public void onSendBtn(ActionEvent actionEvent) {
        String text = inputTextArea.getText();
        if (Objects.equals("", text)) {
            Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "发送消息不能为空", ButtonType.FINISH, ButtonType.CLOSE);
            alert.showAndWait();
            return;
        }
        // 群发消息
        service.multicast(text, user);
        inputTextArea.setText("");
    }

    /**
     * 清空用户输入框
     *
     * @param actionEvent 事件
     */
    public void onEmptyBtn(ActionEvent actionEvent) {
        inputTextArea.setText("");
    }

    /**
     * 打开私聊窗口
     *
     * @param targetUser 目标用户
     */
    private void openPrivateChat(User targetUser) {
        try {
            Stage stage = new Stage();
            FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/privateChat.fxml"));
            Parent root = loader.load();
            // 将聊天双方对象传递到其他controller
            PrivateChatController controller = loader.getController();
            controller.passUser(user, targetUser);
            Scene scene = new Scene(root);
            stage.setTitle(user.getName() + " -> " + targetUser.getName());
            stage.setScene(scene);
            stage.setResizable(false);
            stage.show();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
}
